import logging
import requests
import concurrent.futures
from pathlib import Path
from typing import Any, Dict, List, Tuple
from tqdm import tqdm

from .utils import load_json_file, save_json_file

INVALID_URLS_PATH = Path("data/invalid/invalid_urls.json")

def load_invalid_urls() -> Dict[str, str]:
    """加载无效URL缓存"""
    if not INVALID_URLS_PATH.exists():
        return {}
    data = load_json_file(INVALID_URLS_PATH)
    if isinstance(data, dict):
        return data
    return {}

def save_invalid_urls(invalid_urls: Dict[str, str]):
    """保存无效URL缓存"""
    save_json_file(INVALID_URLS_PATH, invalid_urls)

def validate_source_url(source: Dict[str, Any]) -> Tuple[Dict[str, Any], bool, str]:
    """验证单个书源的URL，返回源、验证结果和原因"""
    url = source.get("bookSourceUrl")
    if not url:
        return source, False, "missing_url"

    try:
        response = requests.head(url, timeout=10, allow_redirects=True)
        response.raise_for_status()
        return source, True, "valid"
    except requests.Timeout:
        return source, False, "timeout"
    except requests.RequestException:
        return source, False, "network_error"

def validate_sources(sources: List[Dict[str, Any]]) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]:
    """
    验证书源列表。
    - 检查URL有效性
    - 检查基本结构
    """
    logging.info(f"开始验证 {len(sources)} 个书源...")
    invalid_cache = load_invalid_urls()
    
    valid_sources = []
    invalid_sources = []
    
    sources_to_validate = []
    for source in sources:
        if not all(k in source for k in ["bookSourceName", "bookSourceUrl", "bookSourceGroup"]):
            source["validation_error"] = "missing_required_keys"
            invalid_sources.append(source)
        elif source.get("bookSourceUrl") in invalid_cache:
            source["validation_error"] = invalid_cache[source.get("bookSourceUrl")]
            invalid_sources.append(source)
        else:
            sources_to_validate.append(source)

    logging.info(f"需要进行网络验证的书源数量: {len(sources_to_validate)}")

    newly_invalid = {}
    with concurrent.futures.ThreadPoolExecutor(max_workers=50) as executor:
        future_to_source = {executor.submit(validate_source_url, source): source for source in sources_to_validate}
        
        # 使用tqdm显示进度
        for future in tqdm(concurrent.futures.as_completed(future_to_source), total=len(sources_to_validate), desc="验证URL"):
            source, is_valid, reason = future.result()
            if is_valid:
                valid_sources.append(source)
            else:
                source["validation_error"] = reason
                invalid_sources.append(source)
                if source.get("bookSourceUrl"):
                    newly_invalid[source.get("bookSourceUrl")] = reason

    if newly_invalid:
        invalid_cache.update(newly_invalid)
        save_invalid_urls(invalid_cache)
        logging.info(f"向缓存中添加了 {len(newly_invalid)} 个新的无效URL。")

    logging.info(f"验证完成。有效: {len(valid_sources)}, 无效: {len(invalid_sources)}")
    return valid_sources, invalid_sources
